Procesamiento de Audio en Formato WAV

Autor: Alejandro Higuera Castro

Fecha: 9 de julio de 2020

La demostración del módulo consta de 6 partes:

  1. Reproducción lenta del audio.
  2. Reproducción rápida del audio.
  3. Reproducción hacia atrás del audio
  4. Limpiar el audio de ruido de alta frecuencia.
  5. Ecualización de las frecuencias bajas y altas del audio.
  6. Mezcla de dos audios en el mismo archivo.

Introducción

Como proyecto para el curso de Introducción a las Ciencias de la Computación en el semestre 2020-1S desarrollé un notebook en Google Colaboratory (iPython) para el análisis y modificación de audio en un formato wav, que viene acompañado del módulo ColabAudioProcessing para proveer un diseño modular al Notebook, el cuál está disponible para su instalación desde pip.

El sonido en el mundo físico son vibraciones que se propagan viajando por el aire o otro medio y que pueden ser escuchadas por el oído de una persona o un animal. Por otra parte, en el mundo diigtal el sonido son codificaciones de señales eléctricas que representan una onda sonora, parte de ello tenemos procesos como el muestreo y la cuantificación digital de la señal eléctrica, esto nos plantea problemáticas como su edición, transporte y reproducción en medios digitales.

Existen múltiples formatos digitales para el almacenamiento de sónido, algunos de los más conocidos .m4a, .mp3, .ogg, .aif, .wma, .wav, entre otros. En este proyecto buscamos manipular en particular el formato .wav que se caracteriza por la aseucncia de compresión en sus datos, su excelente calidad y su amplio soporte para cai todos los códes de audio actuales.

El módulo ColabAudioProcessing provee herramientas básicas y facilidades para la edición y análisis de audio en formato .wav. Puede ser instalado con el instalador de Paquetes de Python (PIP), dado que se encuentra publicado en el Índice de paquetes de Python pipy.org. Este integra las librerias Numpy, Scipy y Matplotlib para desplegar más de 10 funciones integradas que son muy útiles para la manipulación de archivos en el formato .wav, en este notebook es posible ver la demostración de la mayoría de estas funciones.

Objetivos

  1. Desarrollar un módulo de Python para facilitar el análisis y procesamiento básico de archivos de audio en formato .wav.
  2. Analizar el funcionamiento de los filtros de paso bajo y paso alto, para la ecualización y filtrado de ruido.
  3. Cambiar la velocidad en que se reproduce un archivo .wav, filtrar ruido de alta frecuencia, reproducir un archivo de audio hacia atrás, combinar archivos de audio y mezclar dos archivos de audio.

Módulo audio.ColabAudioProcessing

El notebook fue diseñado bajo los parámetros de diseño modular, pensando en un código limpio, entendible y fácil de reutilizar. Para ello se creó un modulo externo para el fácil despliegue de las funciones necesarias para el proyecto. pypi.org/project/ColabAudioProcessing

El módulo puede ser cargado desde el Notebook o con PIP.

In [ ]:
!pip install ColabAudioProcessing
from ColabAudioProcessing.audio import * 
In [ ]:
#Código del módulo
from scipy.io import wavfile
import numpy as np
import IPython.display as ipd
from scipy.fftpack import *
import matplotlib.pyplot as plt
import math

def playAudio(file):
    """
    Muestra en pantalla el reproductor de iPython Display para un archivo de
    formato .wav.

    Parámetros
    ----------
    file: string
        Nombre del archivo en formato .wav que contiene audio en formato
        mono o estéreo.
    Retorna
    ----------
    Reproductor en pantalla de iPython con el audio estipulado

    """

    return ipd.Audio(file)

def ReadAudio(file):
    """
    Retorna la tasa de muestras por minuto y la matriz con los datos del audio}
    en formato mono o estéreo.

    Parámetros
    ----------
    file: string
        Nombre del archivo en formato .wav que contiene audio en formato
        mono o estéreo.
        
    Retorna
    --------
    List: 
        [rate,data]
    rate: int 
        Muestras por segundo
    data: numpy ndarray 
        Matriz con audio en mono o estéreo
    """
    rate,data=wavfile.read(file)
    return [rate,data]

def WriteAudio(filename,rate,matrix):
    """
    Escribe un archivo de audio .wav a partir de una matriz numpy con los datos
    del audio en mono o estéreo y la tasa de muestras por segundo.

    Parámetros
    ----------
    filename: string
        Nombre del archivo de salida .wav.
    matrix: numpy ndarray
        Matriz con audio en mono o estéreo.
    rate: int
        Tasa de muestras por minuto del audio.
    
    Retorna
    --------
    Archivo de formato wav con nombre establecido por el usuario <filename>.
    """
    wavfile.write(filename,rate,matrix)

def Speed_Rep(input_filename,speed,output_filename):
    """
    Muestra en pantalla el reproductor de audio y guarda el audio con la
    velocidad dada por el usuario para el archivo .wav estipulado.

    Parámetros
    ----------
    input_filename: string
         Nombre o localización/path del archivo .wav de entrada.
    speed: float
        Velocidad con la que se va a reproducir el audio de destino.
    output_filename: string
         Nombre o localización/path del archivo .wav de salida
    
    Retorna
    ----------
    Reproductor en pantalla de iPython con el audio con la velocidad deseada.

    """
    rate,data=ReadAudio(input_filename)
    WriteAudio(output_filename,int(rate*speed),data)
    print(f"El archivo se guardo con éxito como {output_filename}")
    return playAudio(output_filename)

def Inverse_Rep(input_filename,output_filename):
    """
    Muestra en pantalla el reproductor de audio y guarda el audio reproducido
    desde atrás en el archivo .wav estipulado.

    Parámetros
    ----------
    input_filename: string
         Nombre o localización/path del archivo .wav de entrada.
    output_filename: string
         Nombre o localización/path del archivo .wav de salida
    Retorna
    ----------
    Reproductor en pantalla de iPython con el audio hacia atrás.
    """
    
    rate,data=ReadAudio(input_filename)
    #Convertimos a mono el audio original
    data=ConvertToMono(data)
    #Leemos la matriz desde atrás usando la notación de slicing de listas
    WriteAudio(output_filename,rate,data[::-1])
    print(f"El archivo se guardo con éxito como {output_filename}")
    return playAudio(output_filename)

def ConvertToMono(data):
    """
    Retorna un array de Numpy con la matriz de audio convertida a mono con el
    mismo dtype de Numpy que el original.

    Parámetros
    ----------
    data: numpy ndarray
        Matriz de Numpy que contiene audio en formato mono o estéreo.
    
    Retorna
    ----------
    mono: numpy ndarray
        Matriz de Numpy que contiene audio en mono.
    """
    #Se procede a leer el audio
    if len(data.shape)==1:
        canales=1
    else:  
        canales=data.shape[1]

    if canales==1:
        mono=data
    #En caso de que el audio sea de formato estéreo procede a su conversión
    elif canales==2:
        mono=[]
        stereo_dtype=data.dtype
        #Se obtienen los vectores correspondientes a cada canal de audio
        l=data[:,0]
        r=data[:,1]
        #Se suma cada canal de audio para obtener uno solo
        for i in range(len(data)):
            d=(l[i]/2)+(r[i]/2)
            mono.append(d)
        mono=np.array(mono,dtype=stereo_dtype)
    return mono


def Lowpass(data,alpha):
    """
    Filtro exponencial EMA de paso bajo que recibe una matriz con audio en
    mono y retorna una matriz con audio en mono del mismo tipo con el Filtro
    aplicado.

    Parámetros
    ----------
    data: Matriz Numpy ndarray
         Matriz con los datos de un audio mono.
    alpha: float
         Factor entre 0 y 1 que determina el suavizado y aplicación del filtro.
    
    Retorna
    ----------
    filtered: numpy ndarray
        Matriz de Numpy que contiene audio en mono filtrado, con el mismo dtype
        del original.
    """
    f0=alpha*data[0]
    filtered=[f0]
    for i in range (1,len(data)):
        #y[i] := α * x[i] + (1-α) * y[i-1]
        f=alpha*data[i]+(1-alpha)*filtered[i-1]
        filtered.append(f)

    filtered=np.array(filtered,dtype=data.dtype)
    return filtered

def Highpass(data,alpha):
    """
    Filtro exponencial EMA de paso alto que recibe una matriz con audio en
    mono y retorna una matriz con audio en mono del mismo tipo con el Filtro
    aplicado.

    Parámetros
    ----------
    data: Matriz Numpy ndarray
         Matriz con los datos de un audio mono.
    alpha: float
         Factor entre 0 y 1 que determina el suavizado y aplicación del filtro.

    Retorna
    ----------
    filtered: numpy ndarray
        Matriz de Numpy que contiene audio en mono filtrado, con el mismo dtype
        del original.
    """
    f_Lowpass=Lowpass(data,alpha)
    filtered=[]
    for i in range(len(data)):
        f=data[i]-f_Lowpass[i]
        filtered.append(f)

    filtered=np.array(filtered,dtype=data.dtype)
    return filtered

def Frequency_Cutoff(type,frequency,input_filename,output_filename):
    """
    Aplica el filtro exponencial EMA de acuerdo al tipo especificado por el
    usuario (Lowpass o Highpass).

    Parámetros
    ----------
    type: string (low or high)
        Tipo de filtro (Paso bajo o paso alto).
    frequency: float
        Frecuencia (Hz) de corte para aplicación de filtro.
    input_filename: string
         Nombre o localización/path del archivo .wav de entrada.
    output_filename: string
         Nombre o localización/path del archivo .wav de salida

    Retorna
    ----------
    filtered: numpy ndarray
        Archivo de formato wav con nombre establecido por el usuario 
        <output_filename>.
    """
    #Relación entre la frecuencia de corte y el parámetro alpha
    rate,data=ReadAudio(input_filename)
    dt=1/rate
    alpha=(2*math.pi*dt*frequency)/((2*math.pi*dt*frequency)+1)

    print(f"α={alpha}")
    
    if type=="low":
        data_f=Lowpass(data,alpha)
    elif type=="high":
        data_f=Highpass(data,alpha)
    WriteAudio(output_filename,rate,data_f)
    print(f"El archivo se guardo con éxito como {output_filename}")

def Combinar_Audios(audio1,audio2,output_filename):
    """
    Muestra en pantalla el reproductor de audio y guarda el audio que combina 
    los dos audios de entrada.
    
    Parámetros
    ----------
    audio1: string
         Nombre o localización/path del archivo .wav de entrada.
    audio2: string
         Nombre o localización/path del archivo .wav de entrada.    
    output_filename: string
         Nombre o localización/path del archivo .wav de salida
    
    Retorna
    ----------
    Reproductor en pantalla de iPython con el audio que comnbina los audios de
    entrada.
    
    """    
    rate_1,data_1=ReadAudio(audio1)
    rate_2,data_2=ReadAudio(audio2)

    if len(data_1)>len(data_2):
        base_data=data_1.copy()
        insert_data=data_2.copy()
    else:
        base_data=data_2.copy()
        insert_data=data_1.copy()
        
    for i in range (0,int(len(insert_data))):
        base_data[i]=base_data[i]/2+insert_data[i]/2
        
    WriteAudio(output_filename,(rate_1+rate_2)//2,base_data)
    print(f"El archivo se guardo con éxito como {output_filename}")
    return playAudio(output_filename)

def FFT_Graphing(Graph_Title,data_1,rate_1,audio1_title,data_2,rate_2,audio2_title):
    """
    Grafica la transformada de fourier de dos audios, donde el eje x se
    muestra como la frecuencia en Hertz y el eje y la amplitud. Esto permite
    comparar de manera objetiva dos audios en su dominio frecuencia.

    Parámetros
    ----------
    Graph_Title: string
        Título de la gráfica.
    data_1: numpy ndarray
        Matriz con audio en mono.
    rate_1: int
        Muestras por segundo del audio.
    audio1_title: string
        Nombre a mostrar en la gráfica.
    data_2: numpy ndarray
        Matriz con audio en mono.
    rate_2: int
            Muestras por segundo del audio.
    audio2_title: string
        Nombre a mostrar en la gráfica.
    
    Retorna
    --------
    Gráfico de Matplotlib con la Transformada Rápida de Fourier de los audios de
    entrada.
    """
    plt.title(Graph_Title)
    plt.xlabel("Frecuencia (Hz)")
    plt.ylabel("Amplitud")

    fft_data_1=abs(fft(data_1))
    frecs_1=fftfreq(len(fft_data_1),(1/rate_1))
    x1=frecs_1[:(len(fft_data_1)//2)]
    y1=fft_data_1[:(len(fft_data_1)//2)]

    fft_data_2=abs(fft(data_2))
    frecs_2=fftfreq(len(fft_data_2),(1/rate_2))
    x2=frecs_2[:(len(fft_data_2)//2)]
    y2=fft_data_2[:(len(fft_data_2)//2)]

    plt.plot(x1,y1,color="r",label=audio1_title)
    plt.plot(x2,y2,color="g",label=audio2_title)
    plt.legend(loc='upper right', borderaxespad=0.)
    plt.show()

def AudioGraphing(Graph_Title,data_1,rate_1,audio1_title,data_2,rate_2,audio2_title):
        """
        Grafica un audio/señal en el dominio tiempo, en el eje y se muestra la 
        señal y en el eje x el tiempo.
    
        Parámetros
        ----------
        Graph_Title: string
            Título de la gráfica.
        data_1: numpy ndarray
            Matriz con audio en mono.
        rate_1: int
            Muestras por segundo del audio.
        audio1_title: string
            Nombre a mostrar en la gráfica.
        data_2: numpy ndarray
            Matriz con audio en mono.
        rate_2: int
                Muestras por segundo del audio.
        audio2_title: string
            Nombre a mostrar en la gráfica.

        Retorna
        --------
        Gráfico de Matplotlib con los audios de entrada, en el eje x la amplitud
        y en el eje y el tiempo en segundos.
        """
        plt.title(Graph_Title)
        plt.xlabel('Tiempo (s)')
        plt.ylabel('Amplitud')

        data_1=ConvertToMono(data_1)
        tiempo_1=np.arange(len(data_1))/float(rate_1)

        data_2=ConvertToMono(data_2)
        tiempo_2=np.arange(len(data_2))/float(rate_2)

        plt.fill_between(tiempo_1,data_1,color='b',label=audio1_title) 
        plt.fill_between(tiempo_2,data_2,color='m',label=audio2_title) 
        plt.legend(loc='upper right', borderaxespad=0.)
        plt.show()

def AdjustVolume(input_filename,volume,output_filename):
    """
    Muestra en pantalla el reproductor de audio y guarda el audio con la
    velocidad dada por el usuario para el archivo .wav estipulado.

    Parámetros
    ----------
    input_filename: string
         Nombre o localización/path del archivo .wav de entrada.
    volume: float
         Porcentaje de volumen del audio de salida.
    output_filename: string
         Nombre o localización/path del archivo .wav de salida
    
    Retorna
    ----------
    Reproductor en pantalla de iPython con el audio con el volumen deseado.
    """
    rate,data=ReadAudio("sweet.wav")
    #Convertirlo a mono, hace menos pesado y rápido de procesar el audio
    data=ConvertToMono(data)
    adjusted=[]

    #Multiplicamos la amplitud actual por el factor de aumento deseado
    for i in range(len(data)):
      adjust=(volume/100)*data[i]
      adjusted.append(adjust)

    adjusted=np.array(adjusted,dtype=data.dtype)
    WriteAudio(output_filename,rate,adjusted)
    print(f"El archivo se guardo con éxito como {output_filename}")
    return playAudio(output_filename)

Importación de sonidos en formato .wav desde el repositorio

In [ ]:
!wget https://raw.githubusercontent.com/DarkNightSoldier/AudioProcessing/master/Happy.wav
!wget https://raw.githubusercontent.com/DarkNightSoldier/AudioProcessing/master/sweet.wav
!wget https://raw.githubusercontent.com/DarkNightSoldier/AudioProcessing/master/hfnoise.wav

1. Reproducción lenta del audio

Para reducir la velocidad del audio debemos reducir el número de muestras por segundo del audio.

In [ ]:
Velocidad = 0.9 #@param {type:"slider", min:0.4, max:1, step:0.05}
Speed_Rep("Happy.wav",Velocidad,"slow.wav")
El archivo se guardo con éxito como slow.wav
Out[ ]:

2. Reproducción rapida del audio

Para aumentar la velocidad del audio debemos aumentar el número de muestras por segundo del audio.

In [ ]:
Velocidad = 1.65 #@param {type:"slider", min:1, max:5, step:0.05}
Speed_Rep("Happy.wav",Velocidad,"fast.wav")
El archivo se guardo con éxito como fast.wav
Out[ ]:

3. Reproducción hacia atrás del audio

Para reproducir el audio hacia atrás basta con leer la matriz desde atrás hacia adelante, conservando la misma tasa de muestras por segundo.

In [ ]:
Inverse_Rep("Happy.wav","inverse.wav")
El archivo se guardo con éxito como inverse.wav
Out[ ]:

Filtros

Filtro de paso bajo

Este tipo de filtro se caracteriza por el paso de las frecuencias más bajas y la atenuación de las frecuencias más altas, lo que lo posiciona como útil para la disminución del ruido de alta frecuencia.

El filtro EMA de paso bajo consiste en obtener un valor filtrado a partir de la aplicación de la siguiente expresión con cada uno de los datos de la matriz del audio mono:

$y[i]= \alpha \cdot x[i] + (1-\alpha) \cdot y[i-1]$

Donde:

  • y[i]=Valor filtrado.
  • α=Factor de filtrado (0-1).
  • x[i]=Valor muestreado de la señal.
  • y[i-1]=Valor filtrado anterior.

Filtro de paso alto

Este tipo de filtro se caracteriza por el paso de las frecuencias más altas y la atenuación de las frecuencias más bajas, lo que lo posiciona como útil para la disminución del ruido de baja frecuencia.

El filtro EMA de paso alto consiste en obtener un valor filtrado a partir de la aplicación de la siguiente expresión con cada uno de los datos de la matriz del audio mono:

$y[i]=x[i]-Lowpass[i]$

Donde:

  • y[i]= Valor filtrado.
  • lowpass[i]= Valor del filtro de paso bajo.

4. Limpieza del ruido de alta frecuencia

Reducción del ruido de alta frecuencia de un audio

Para disminuir el ruido de alta frecuencia es posible optar por aplicar un filtro de paso bajo a una frecuencia de corte determinada.

La relación de la frecuencia de corte con el factor $\alpha$ de filtrado está dada por la ecuación:

$\alpha=\frac {2*\pi*\Delta t*f_c}{(2*math.pi*\Delta t*f_c)+1}$

Donde:

  • $α$=Factor de filtrado

  • $Δt$=Cambio de tiempo ($Δt=\frac{1}{Sample\_rate}$)

  • $f_c$=Frecuencia de corte

In [ ]:
fr=int(input("Especifique la frecuencia de corte en Hz  "))
Frequency_Cutoff("low",fr,"hfnoise.wav","limpieza.wav")
Especifique la frecuencia de corte en Hz  500
α=0.2819698001234662
El archivo se guardo con éxito como limpieza.wav
In [ ]:
rate_1,data_1=ReadAudio("hfnoise.wav")
data_1=ConvertToMono(data_1)

rate_2,data_2=ReadAudio("limpieza.wav")
data_2=ConvertToMono(data_2)

FFT_Graphing("FFT Con Ruido VS Lowpass fc",data_1,rate_1,"Audio sin filtrar",data_2,rate_2,f"Lowpass {fr} Hz")
AudioGraphing("Con Ruido VS Lowpass fc",data_1,rate_1,"Audio sin filtrar",data_2,rate_2,f"Lowpass {fr} Hz")

En la primera gráfica donde encontramos la transformada de fourier del audio mono es posible apreciar una atenuación considerable de la apmplitud de las frecuencias más altas y en el segundo gráfico la eliminación de los picos que representa el ruido agregando un poco de suavidad a la señal original.

In [ ]:
playAudio("hfnoise.wav")
Out[ ]:
In [ ]:
playAudio('limpieza.wav')
Out[ ]:

Reducción de ruido de alta frecuencia con un conjunto de datos

La aplicación de este filtro es posible verla de manera más clara usando un conjunto de datos con ruido de alta frecuencia.

In [ ]:
Noisy_Data=[7729, 7330, 10075, 10998, 11502, 11781, 12413, 12530, 14070, 13789, 18186, 14401, 16691, 16654,
            17424, 21104, 17230, 20656, 21584, 21297, 19986, 20808, 19455, 24029, 21455, 21350, 19854, 23476,
            19349, 16996, 20546, 17187, 15548, 9179, 8586, 7095, 9718, 5148, 4047, 3873, 4398, 2989, 3848, 
            2916, 1142, 2427, 250, 2995, 1918, 4297, 617, 2715, 1662, 1621, 960, 500, 2114, 2354, 2900, 4878,
            8972, 9460, 11283, 16147, 16617, 16778, 18711, 22036, 28432, 29756, 24944, 27199, 27760, 30706, 
            31671, 32185, 32290, 30470, 32616, 32075, 32210, 28822, 30823, 29632, 29157, 31585, 24133, 23245,
            22516, 18513, 18330, 15450, 12685, 11451, 11280, 9116, 7975, 8263, 8203, 4641, 5232, 5724, 4347,
            4319, 3045, 1099, 2035, 2411, 1727, 852, 1134, 966, 2838, 6033, 2319, 3294, 3587, 9076, 5194, 6725,
            6032, 6444, 10293, 9507, 10881, 11036, 12789, 12813, 14893, 16465, 16336, 16854, 19249, 23126, 21461,
            18657, 20474, 24871, 20046, 22832, 21681, 21978, 23053, 20569, 24801, 19045, 20092, 19470, 18446,
            18851, 18210, 15078, 16309, 15055, 14427, 15074, 10776, 14319, 14183, 7984, 8344, 7071, 9675, 5985,
            3679, 2321, 6757, 3291, 5003, 1401, 1724, 1857, 2605, 803, 2742, 2971, 2306, 3722, 3332, 4427, 5762,
            5383, 7692, 8436, 13660, 8018, 9303, 10626, 16171, 14163, 17161, 19214, 21171, 17274, 20616, 18281,
            21171, 18220, 19315, 22558, 21393, 22431, 20186, 24619, 21997, 23938, 20029, 20694, 20648, 21173, 20377,
            19147, 18578, 16839, 15735, 15907, 18059, 12111, 12178, 11201, 10577, 11160, 8485, 7065, 7852, 5865, 4856,
            3955, 6803, 3444, 1616, 717, 3105, 704, 1473, 1948, 4534, 5800, 1757, 1038, 2435, 4677, 8155, 6870, 4611,
            5372, 6304, 7868, 10336, 9091]
#Convertimos los datos en un array de numpy de un canal
Noisy_Data=np.array(Noisy_Data,dtype=np.int16)
data_rate=1

#Filtramos la señal con un filtro de paso bajo
filtered=Lowpass(Noisy_Data,alpha=0.2)

#Graficamos la señal de forma comparativa
FFT_Graphing("FFT señal con ruido vs filtrada",Noisy_Data,data_rate,"Señal con ruido",filtered,data_rate,"Señal filtrada")
AudioGraphing("Señal con ruido vs filtrada",Noisy_Data,data_rate,"Señal con ruido",filtered,data_rate,"Señal filtrada")

En el último gráfico es posible ver con más detalle la eliminación del ruido de alta frecuencia donde se ve una señal suavizada y sin picos. Por otra parte en la primera gráfica donde se encuentra la Transformada de Fourier es posible apreciar la atenuación de las frecuencias más altas las cuales representan el ruido.

5. Ecualización de frecuencias altas y bajas

Para la ecualización de las frecuencias altas y bajas del audio, usamos los filtros de paso bajo y paso alto sobre la canción. La variación del resultado de la ecualización estará dado por el cambio en el factor $\alpha$.

In [ ]:
alpha = 0.2 #@param {type:"slider", min:0, max:1, step:0.01}
rate,data=ReadAudio("Happy.wav")
data=ConvertToMono(data)

data_low=Lowpass(data,alpha)
data_high=Highpass(data,alpha)

FFT_Graphing(f"FFT Original vs Low pass α={alpha}",data,rate,"Original",data_low,rate,"Lowpass")
AudioGraphing(f"Original vs Low pass α={alpha}",data,rate,"Original",data_low,rate,"Lowpass")
FFT_Graphing(f"FFT Original vs High pass α={alpha}",data,rate,"Original",data_high,rate,"Highpass")
AudioGraphing(f"Original vs High pass α={alpha}",data,rate,"Original",data_high,rate,"Highpass")

Dado que la señal es una canción y no tiene ruido anormal, se presenta una atenuación normal de las frecuencias altas y bajas según corresponde la aplicación del filtro. Por otra parte es pobile apreciar una conservación apreciable de la señal original con la aplicación del filtro de paso bajo que se muestra en la primera gráfica, lo cual sugiere que el audio presenta frecuencias bajas y el factor de filtrado $\alpha$ no es lo suficientemente pequeño para una atenuación más amplia en el espectro del audio.

In [ ]:
print(f"Lowpass α={alpha}")
WriteAudio("lowpass.wav",rate,data_low)
playAudio("lowpass.wav")
Lowpass α=0.2
Out[ ]:
In [ ]:
print(f"Highpass α={alpha}")
WriteAudio("highpass.wav",rate,data_high)
playAudio("highpass.wav")
Highpass α=0.2
Out[ ]:

6. Combinar dos audios

In [ ]:
Combinar_Audios("Happy.wav","sweet.wav","Combined.wav")
El archivo se guardo con éxito como Combined.wav
Out[ ]:

7. Ajustar el volumen del audio

Aumento de volumen

Nota: Aumentar el volumen amplifica también aumentar la amplitud del ruido de alta frecuencia, un volumen mayor a 150 que el rudio de alta frecuencia se haga más audible, según el audio elegido puede haber menor o mayor aumento de este ruido. Por ello se limita, por el momento hasta 150%, el aumento de volumen, pues en caso contrario habría que también filtrar el audio de ruido de alta frecuencia.

In [ ]:
Volumen=120 #@param {type:"slider", min:0, max:150, step:1}

AdjustVolume("sweet.wav",Volumen,"up.wav")
El archivo se guardo con éxito como up.wav
Out[ ]:

En la siguiente gráfica, es posible ver en correspondencia este aumento de la amplitud del audio de salida:

In [ ]:
rate_1,data_1=ReadAudio("sweet.wav")
data_1=ConvertToMono(data_1)
rate_2,data_2=ReadAudio("up.wav")

AudioGraphing(f"Original vs Volumen {Volumen}%",data_2,rate_2,f"Volumen al {Volumen}%",data_1,rate_1,"Volumen original")

Disminución del volumen

In [ ]:
Volumen_2=5 #@param {type:"slider", min:0, max:150, step:1}

AdjustVolume("sweet.wav",Volumen_2,"down.wav")
El archivo se guardo con éxito como down.wav
Out[ ]:

En la siguiente gráfica, es posible ver en correspondencia esta reducción de la amplitud del audio de salida:

In [ ]:
rate_a,data_a=ReadAudio("sweet.wav")
data_a=ConvertToMono(data_1)
rate_b,data_b=ReadAudio("down.wav")

AudioGraphing(f"Original vs Volumen {Volumen_2}%",data_a,rate_a,"Volumen original",data_b,rate_b,f"Volumen al {Volumen_2}%")

Bibliografía del proyecto